package reflection_generics_containers.reflection;

import java.io.FileInputStream;
import java.lang.reflect.Method;

/**
 * @author LiuYan
 * @date 2023/7/21
 */
public class CustomClassLoader extends ClassLoader {


    private String classPath;

    public CustomClassLoader(String classPath) {
        this.classPath = classPath;
    }

    private byte[] loadByte(String name) throws Exception {
        name = name.replaceAll("\\.", "/");
        FileInputStream fis = new FileInputStream(classPath + "/" + name + ".class");
        int len = fis.available();
        byte[] data = new byte[len];
        fis.read(data);
        fis.close();
        return data;
    }


    protected Class<?> findClass(String className) throws ClassNotFoundException {
        try {
            byte[] data = loadByte(className);
            return defineClass(className, data, 0, data.length);
        } catch (Exception e) {
            e.printStackTrace();
            throw new ClassNotFoundException();
        }
    }

    protected Class<?> loadClass(String name, boolean resolve)
            throws ClassNotFoundException {
        synchronized (getClassLoadingLock(name)) {
            // First, check if the class has already been loaded
            Class<?> c = findLoadedClass(name);
            if (c == null) {
                // If still not found, then invoke findClass in order
                // to find the class.
                long t0 = System.nanoTime();
                try {
                    //修改classloader的原双亲委派逻辑，从而打破双亲委派
                    if (name.startsWith("reflection_generics_containers.reflection")) {
                        c = findClass(name);
                    } else {
                        c = this.getParent().loadClass(name);
                    }
                } catch (ClassNotFoundException e) {

                }

                if (c == null) {
                    long t1 = System.nanoTime();
                    c = findClass(name);
                    sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                    sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                    sun.misc.PerfCounter.getFindClasses().increment();
                }
            }
            if (resolve) {
                resolveClass(c);
            }
            return c;
        }
    }

    public static void main(String[] args) throws Exception  {
        CustomClassLoader customClassLoader = new CustomClassLoader("E:/java/java8/target/classes");
        Class clazz = customClassLoader.loadClass("reflection_generics_containers.reflection.Person");
        Person person = (Person) clazz.newInstance();
        Method method= clazz.getDeclaredMethod("liuyan", null);
        method.invoke(person, null);
        System.out.println(clazz.getClassLoader());

    }


}
